"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getGraph = getGraph;
exports.getNodeAttr = getNodeAttr;
exports.registerAll = registerAll;
exports.registerAutoSave = registerAutoSave;
exports.registerDbClickNode = registerDbClickNode;
exports.registerDragGraph = registerDragGraph;
exports.registerEdge = registerEdge;
exports.registerEdgeRemove = registerEdgeRemove;
exports.registerHistory = registerHistory;
exports.registerKeyboard = registerKeyboard;
exports.registerLane = registerLane;
exports.registerLaneCellChange = registerLaneCellChange;
exports.registerModuleNode = registerModuleNode;
exports.registerNodeMenuContext = registerNodeMenuContext;
exports.registerNodeNumChange = registerNodeNumChange;
exports.registerResizeLane = registerResizeLane;
exports.registerResizeNode = registerResizeNode;

var _x = require("@antv/x6");

var _antd = require("antd");

var _tools = require("../../tools");

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

var minimumLaneHeight = 50;
var nodeHanlderMap = new Map(); // 获取节点样式

function getNodeAttr(shape, data, assets) {
  if (!shape) return {};
  var handler = nodeHanlderMap.get(shape);

  if (handler) {
    return handler(data, assets);
  }

  return {};
} // 注册节点和线条的样式


function registerAll(list) {
  if (!Array.isArray(list) || list.length === 0) return;
  list.forEach(_ref => {
    var {
      name,
      options,
      type,
      handler
    } = _ref;

    if (type === 'NODE' && handler) {
      nodeHanlderMap.set(name, handler);

      _x.Graph.registerNode(name, options, true);
    } else if (type === 'EDGE') {
      _x.Graph.registerEdge(name, options, true);
    }
  });
} // 默认模型组件样式


function getDefaultModuleNodeAttr(data, assets) {
  var {
    icon
  } = data;
  var image = assets[icon] || icon;
  return {
    icon: {
      xlinkHref: image
    }
  };
} // 注册一个默认的样板组件


function registerModuleNode() {
  nodeHanlderMap.set(_tools.defaultModuleNodeName, getDefaultModuleNodeAttr);

  _x.Graph.registerNode(_tools.defaultModuleNodeName, {
    inherit: 'rect',
    width: 190,
    height: 32,
    markup: [{
      tagName: 'rect',
      selector: 'body'
    }, {
      tagName: 'text',
      selector: 'text'
    }, {
      tagName: 'image',
      selector: 'icon'
    }],
    attrs: {
      body: {
        strokeWidth: 0,
        stroke: '#5F95FF',
        fill: '#fff'
      },
      icon: {
        ref: 'body',
        refX: 10,
        refY: 8,
        width: 16,
        height: 16
      },
      text: {
        refX: 36,
        refY: 17,
        fontSize: 12,
        fill: '#333',
        textAnchor: 'start'
      }
    }
  }, true);
} // 泳道样式


function registerLane() {
  var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  var {
    width = 500,
    height = 200
  } = config;

  _x.Graph.registerNode('lane', {
    width,
    height,
    inherit: 'rect',
    markup: [{
      tagName: 'rect',
      selector: 'body',
      className: 'laneBody'
    }, {
      tagName: 'rect',
      selector: 'nameRect',
      className: 'laneRect'
    }, {
      tagName: 'text',
      selector: 'nameText',
      className: 'laneName'
    }, {
      tagName: 'rect',
      selector: 'bottomBorder',
      className: 'resizeBorder'
    }],
    attrs: {
      body: {
        fill: 'transparent',
        stroke: '#f00',
        strokeWidth: 0,
        cursor: 'default'
      },
      nameRect: {
        width: 30,
        refHeight: '100%',
        fill: '#EAFEEC',
        stroke: '#fff',
        strokeWidth: 0,
        x: 0,
        cursor: 'default'
      },
      nameText: {
        ref: 'nameRect',
        textAnchor: 'middle',
        fontWeight: 'bold',
        fill: '#6A8E67',
        fontSize: 12,
        cursor: 'default'
      },
      bottomBorder: {
        refWidth: '100%',
        height: 2,
        stroke: '#9BD787',
        refY: '100%',
        refX: 0,
        y: -3,
        cursor: 'row-resize'
      }
    }
  }, true);
} // 默认线条


function registerEdge() {
  _x.Graph.registerEdge(_tools.defaultEdgeShapeName, {
    inherit: 'edge',
    attrs: {
      line: {
        stroke: '#A2B1C3',
        strokeWidth: 2
      }
    },
    label: {
      attrs: {
        label: {
          fill: '#A2B1C3',
          fontSize: 12
        }
      }
    }
  }, true);
}

function scroll(startPoint, currentPoint, xAxisRef, yAxisRef) {
  var {
    x: sx,
    y: sy
  } = startPoint || {
    x: 0,
    y: 0
  };
  var {
    x: cx,
    y: cy
  } = currentPoint;
  var [ox, oy] = [sx - cx, sy - cy];
  xAxisRef.current.scrollLeft = xAxisRef.current.scrollLeft + ox;
  yAxisRef.current.scrollTop = yAxisRef.current.scrollTop + oy;
  startPoint.x = cx;
  startPoint.y = cy;
} // 拖拽移动画面


function registerDragGraph(graph, xAxisRef, yAxisRef) {
  var startPoint;
  graph.on('node:mousedown', _ref2 => {
    var {
      e,
      cell
    } = _ref2;
    var {
      target,
      clientX: x,
      offsetY: y
    } = e;
    var {
      data: {
        type
      }
    } = cell;

    if (target && type === 'lane') {
      startPoint = {
        x,
        y
      };
    }
  });
  graph.on('node:mousemove', _ref3 => {
    var {
      e,
      cell
    } = _ref3;
    var {
      target,
      clientX: x,
      clientY: y
    } = e;
    var {
      data: {
        type
      }
    } = cell;

    if (target && type === 'lane') {
      scroll(startPoint, {
        x,
        y
      }, xAxisRef, yAxisRef);
    }
  });
  graph.on('node:mouseup', () => {
    startPoint = undefined;
  });
  graph.on('blank:mousedown', _ref4 => {
    var {
      e
    } = _ref4;
    var {
      clientX: x,
      clientY: y
    } = e;
    startPoint = {
      x,
      y
    };
  });
  graph.on('blank:mousemove', _ref5 => {
    var {
      e
    } = _ref5;
    var {
      clientX: x,
      clientY: y
    } = e;
    scroll(startPoint, {
      x,
      y
    }, xAxisRef, yAxisRef);
  });
  graph.on('blank:mouseup', () => {
    startPoint = undefined;
  });
  yAxisRef.current.addEventListener('mousewheel', mouseScroll); // 鼠标滚轮左右滚动

  function mouseScroll(e) {
    var {
      wheelDeltaX: x,
      wheelDeltaY: y
    } = e;
    scroll({
      x: 0,
      y: 0
    }, {
      x,
      y
    }, xAxisRef, yAxisRef);
  }

  return function () {
    if (yAxisRef.current) {
      yAxisRef.current.removeEventListener('mousewheel', mouseScroll);
    }
  };
} // 控制连接桩显示/隐藏


var showPorts = (ports, show) => {
  if (!ports) return;

  for (var i = 0, len = ports.length; i < len; i = i + 1) {
    ports[i].style.visibility = show ? 'visible' : 'hidden';
  }
}; // 注册泳道的拖拽改变尺寸


function registerResizeLane(graph, onLaneResize) {
  var dragNode = undefined;
  var offsetY = undefined;
  var oHeight = undefined;
  var minHeight = minimumLaneHeight;
  graph.on('node:mousedown', _ref6 => {
    var {
      e,
      x,
      y,
      cell,
      node
    } = _ref6;
    var {
      target
    } = e;

    if (target && target.className.baseVal === 'resizeBorder') {
      dragNode = cell;
      offsetY = y;
      oHeight = node.size().height;
      var children = node.getChildren();

      if (Array.isArray(children) && children.length) {
        minHeight = Math.max(...children.map(child => child.size().height));
      }
    }
  });
  graph.on('node:mousemove', _ref7 => {
    var {
      y,
      node
    } = _ref7;
    if (!dragNode) return;
    var {
      width
    } = node.size();
    var height = (oHeight || 0) + y - (offsetY || 0);
    onLaneResize && onLaneResize(dragNode, width, height, minHeight);
  });
  graph.on('node:mouseup', () => {
    dragNode = undefined;
    offsetY = undefined;
    oHeight = undefined;
    minHeight = minimumLaneHeight;
  });
} // 节点双击事件


function registerDbClickNode(graph, setCurrentCell, handlerActions) {
  graph.on('node:dblclick', _ref8 => {
    var {
      node
    } = _ref8;
    if (node.data.type !== 'node') return;
    setCurrentCell(node);
    handlerActions && handlerActions('edite');
  });
} // 节点连线点显示的事件


function registerResizeNode(graph) {
  graph.on('node:mouseenter', _ref9 => {
    var {
      node,
      view
    } = _ref9;
    if (node.data.type !== 'node') return;
    var container = view.container;
    var ports = container.querySelectorAll('.x6-port-body');
    showPorts(ports, true);
  });
  graph.on('node:mouseleave', _ref10 => {
    var {
      node,
      view
    } = _ref10;
    if (node.data.type !== 'node') return;
    var container = view.container;
    var ports = container.querySelectorAll('.x6-port-body');
    showPorts(ports, false);
  });
} // 右键显示按钮


function registerNodeMenuContext(graph, menuRef, callback) {
  graph.on('node:contextmenu', _ref11 => {
    var {
      e,
      x,
      y,
      cell
    } = _ref11;
    if (cell.data.type === 'lane') return;
    var menuContainer = menuRef.current;
    var {
      clientWidth,
      clientHeight
    } = menuContainer;
    menuContainer.style.left = "".concat(x - clientWidth / 2, "px");
    menuContainer.style.top = "".concat(y - clientHeight / 2, "px");
    callback && callback(cell);
  });
} // 监听元素变化（节点和线）


function registerAutoSave(graph, callback) {
  graph.on('cell:added', /*#__PURE__*/_asyncToGenerator(function* () {
    yield (0, _tools.autoSaveJson)(null, graph, callback);
  }));
  graph.on('cell:removed', /*#__PURE__*/_asyncToGenerator(function* () {
    yield (0, _tools.autoSaveJson)(null, graph, callback);
  }));
  graph.on('cell:changed', /*#__PURE__*/_asyncToGenerator(function* () {
    yield (0, _tools.autoSaveJson)(null, graph, callback);
  }));
} // 删除连线


function registerEdgeRemove(graph, callback) {
  graph.on('edge:mouseenter', _ref15 => {
    var {
      edge
    } = _ref15;
    edge.addTools([{
      name: 'button-remove',
      args: {
        distance: -40,

        onClick(_ref16) {
          var {
            view
          } = _ref16;
          var edge = view.cell;
          callback && callback(edge);
        }

      }
    }]);
  });
  graph.on('edge:mouseleave', _ref17 => {
    var {
      edge
    } = _ref17;
    edge.removeTools();
  });
} // 节点数量发生变化时


function registerNodeNumChange(graph) {
  graph.on('node:added', _ref18 => {
    var {
      node
    } = _ref18;
    if (!node.parent) return;
    var {
      width: nw
    } = node.size();
    var {
      clientWidth: gw
    } = graph.container;
    var lane = graph.getCellById(node.parent.id);
    var nodes = lane.getChildren();
    var maxWidth = Math.max(gw, ...(nodes || []).map(n => n.position().x + n.size().width + nw + 100));

    if (maxWidth !== gw) {
      graph.getNodes().filter(n => n.shape === 'lane').forEach(laneNode => {
        var {
          height: lh
        } = laneNode.size();
        laneNode.size(maxWidth, lh);
      });
      graph.container.style.width = maxWidth + 'px';
    }
  });
} // 监听history变化


function registerHistory(graph, configs) {
  var {
    setCanRedo,
    setCanUndo,
    onUndoOrRedo
  } = configs; // 节点和边的添加和移除可能涉及到后端交互，因此这里交给开发者处理，组件不做处理

  graph.history.on('undo', args => {
    onUndoOrRedo && onUndoOrRedo('undo', graph, args);
  });
  graph.history.on('redo', args => {
    onUndoOrRedo && onUndoOrRedo('redo', graph, args);
  });
  graph.history.on('change', () => {
    setCanRedo(graph.history.canRedo());
    setCanUndo(graph.history.canUndo());
  });
} // 泳道高度调整


function registerLaneCellChange(cell, onLaneSizeChanged) {
  cell.on('change:size', () => onLaneSizeChanged());
} // 注册快捷键


function registerKeyboard(graph, onActions) {
  // #region 快捷键与事件
  // copy
  graph.bindKey(['meta+c', 'ctrl+c'], () => {
    onActions && onActions('copy');
    return false;
  }); // paste

  graph.bindKey(['meta+v', 'ctrl+v'], () => {
    onActions && onActions('paste');
    return false;
  }); //undo

  graph.bindKey(['meta+z', 'ctrl+z'], () => {
    onActions && onActions('undo');
    return false;
  }); // redo

  graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
    onActions && onActions('redo');
    return false;
  }); //delete

  graph.bindKey('backspace', () => {
    onActions && onActions('delete');
  }); // zoom bigger

  graph.bindKey(['ctrl+1', 'meta+1'], () => {
    onActions && onActions('bigger');
  }); // zoom smaller

  graph.bindKey(['ctrl+2', 'meta+2'], () => {
    onActions && onActions('smaller');
  }); // clearStorage

  graph.bindKey(['ctrl+e', 'meta+e'], () => {
    onActions && onActions('clearStorage');
  });
} // 初始化画布


function getGraph(container, minimapContainer, config) {
  var {
    onAddLink,
    defaultEdgeShape
  } = config || {};
  var graph = new _x.Graph({
    panning: false,
    keyboard: true,
    history: {
      enabled: true,
      ignoreAdd: false,
      ignoreRemove: false,
      ignoreChange: false,

      beforeAddCommand(event, args) {
        var {
          key,
          cell
        } = args;
        if (args.key === 'tools') return false; // 数据如果影响到节点样式会被记录到撤销队列，但是撤销的时候只能恢复样式，无法恢复数据
        // 因此禁止节点数据更新被记录到队列中

        if (event === 'cell:change:*' && cell.isNode() && key === 'attrs') {
          return false;
        }

        if (cell.isEdge()) {
          if (!cell.data) return false;
          var {
            source,
            target
          } = cell.data;
          if (!source || !target) return false;
        }

        return true;
      }

    },
    grid: {
      size: 10,
      visible: true,
      type: 'mesh'
    },
    container: container,
    selecting: {
      enabled: true,

      filter(node) {
        return node.shape !== 'lane';
      }

    },
    clipboard: true,
    resizing: {
      enabled: cell => {
        return cell.type === 'node';
      }
    },
    connecting: {
      allowNode: options => {
        var {
          targetCell
        } = options;
        return targetCell.type === 'node';
      },
      router: 'manhattan',
      connector: {
        name: 'rounded',
        args: {
          radius: 8
        }
      },
      anchor: 'center',
      allowBlank: false,
      allowEdge: false,
      allowLoop: false,
      allowMulti: false,
      snap: {
        radius: 20
      },

      createEdge() {
        return new _x.Shape.Edge({
          shape: defaultEdgeShape,
          attrs: {
            line: {
              stroke: '#A2B1C3',
              strokeWidth: 2
            }
          }
        });
      },

      validateEdge(_ref19) {
        var {
          edge
        } = _ref19;
        var sourceCell = edge.getSourceCell();
        var targetCell = edge.getTargetCell();

        if (!sourceCell || !targetCell || !sourceCell.parent || !targetCell.parent) {
          return false;
        }

        var sourceParentSort = sourceCell.parent.data.sort;
        var targetParentSort = targetCell.parent.data.sort; // 只能相邻层级节点进行连线

        if (Math.abs(sourceParentSort - targetParentSort) !== 1) {
          _antd.message.info('只能对相邻的层级进行连线');

          return false;
        }

        edge.data = {
          id: "".concat(sourceCell.id, "_").concat(targetCell.id),
          type: 'link'
        };
        onAddLink && onAddLink(edge);
        return false;
      }

    },
    translating: {
      restrict(cellView) {
        var cell = cellView.cell;
        var parentId = cell.prop('parent');

        if (parentId) {
          var parentNode = graph.getCellById(parentId);

          if (parentNode) {
            return parentNode.getBBox().moveAndExpand({
              x: 32,
              y: 0,
              width: -32,
              height: -4
            });
          }
        }

        return cell.getBBox();
      }

    }
  });
  return graph;
}